package com.it.flowable.controller;

import com.it.flowable.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 开启流程
 * <br/>
 * 获取所有流程, 历史的,进行中的
 * 获取流程详情, 环境变量, 当前审批节点, BPM图
 *
 */
@Slf4j
@RestController
@RequestMapping("/api/process/exec")
public class ProcessExecController {

    @Resource
    private TaskService taskService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private IdentityService identityService;

    @Resource
    private HistoryService historyService;

    /**
     * 查询所有流程
     */
    @GetMapping("/getPage")
    public List<TaskInfoVo> getPage(TaskQo taskQo) {
        TaskQuery taskQuery = taskService.createTaskQuery();
        if (taskQo.getAssign() != null && !taskQo.getAssign().isEmpty()) {
            taskQuery.taskAssignee(taskQo.getAssign());
        }
        if (taskQo.getProcessDefinitionKey() != null && !taskQo.getProcessDefinitionKey().isEmpty()) {
            taskQuery.processDefinitionKey(taskQo.getProcessDefinitionKey());
        }
        if (taskQo.getProcessInstanceId() != null && !taskQo.getProcessInstanceId().isEmpty()) {
            taskQuery.processDefinitionKey(taskQo.getProcessInstanceId());
        }

        List<Task> tasks = taskQuery
                .includeProcessVariables()  // 包含流程变量
                .includeTaskLocalVariables() // 包含任务本地变量
                .list();
        // 转换成VO
        // forms
        List<TaskInfoVo> taskInfoVos = tasks.stream()
                .map(task -> {
                    Map<String, Object> variables = taskService.getVariables(task.getId());

                    return new TaskInfoVo(task, variables);
                })
                .collect(Collectors.toList());
        return taskInfoVos;
    }

    /**
     * 发起流程
     */
    @PostMapping("/startProcess")
    public ResponseEntity<String> startProcess(@RequestBody ApprovalVo request) {
        try {
            identityService.setAuthenticatedUserId(request.getUserId()); // 启动流程时, 会自动设置initiator;
            // identityService.setAuthenticatedUserId / startEvent 的 initiator 配置 / Variables 中的 initiator 变量
            // startEvent initiator：是配置指令，告诉引擎自动创建特定的流程变量
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(request.getProcessDefinitionKey(), request.getVariables());
            return ResponseEntity.ok("流程已启动，流程实例ID: " + processInstance.getId());
        } finally {
            identityService.setAuthenticatedUserId(null);
        }

    }

    @GetMapping("/getHistoryPage")
    public List<HistoricProcessInstance> getHistoryPage(ProcessInstanceQueryVo queryVo) {
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();

        // 流程定义相关
        if (StringUtils.hasText(queryVo.getProcessDefinitionId())) {
            query.processDefinitionId(queryVo.getProcessDefinitionId());
        }
        if (StringUtils.hasText(queryVo.getProcessDefinitionKey())) {
            query.processDefinitionKey(queryVo.getProcessDefinitionKey());
        }
        if (StringUtils.hasText(queryVo.getProcessDefinitionName())) {
            query.processDefinitionName(queryVo.getProcessDefinitionName());
        }

        // 流程实例相关
        if (StringUtils.hasText(queryVo.getProcessInstanceId())) {
            query.processInstanceId(queryVo.getProcessInstanceId());
        }
        if (StringUtils.hasText(queryVo.getBusinessKey())) {
            query.processInstanceBusinessKey(queryVo.getBusinessKey());
        }

        // 状态筛选
        if (queryVo.getUnfinished() != null && queryVo.getUnfinished()) {
            query.unfinished();
        }
        if (queryVo.getFinished() != null && queryVo.getFinished()) {
            query.finished();
        }
        if (queryVo.getDeleted() != null && queryVo.getDeleted()) {
            query.deleted();
        }

        // 时间范围
        if (queryVo.getStartedAfter() != null) {
            query.startedAfter(queryVo.getStartedAfter());
        }
        if (queryVo.getStartedBefore() != null) {
            query.startedBefore(queryVo.getStartedBefore());
        }
        if (queryVo.getFinishedAfter() != null) {
            query.finishedAfter(queryVo.getFinishedAfter());
        }
        if (queryVo.getFinishedBefore() != null) {
            query.finishedBefore(queryVo.getFinishedBefore());
        }

        // 启动用户
        if (StringUtils.hasText(queryVo.getStartedBy())) {
            query.startedBy(queryVo.getStartedBy());
        }

        // 排序和分页
        List<HistoricProcessInstance> res = query
                .orderByProcessInstanceStartTime().desc()
                .listPage(queryVo.getFirstResult(), queryVo.getMaxResults());

        return res;
    }


    @GetMapping("/getProcessInstanceDetail")
    public ProcessInstanceDetail getProcessInstanceDetail(String processInstanceId) {
        ProcessInstanceDetail detail = new ProcessInstanceDetail();

        // 1. 获取流程实例基本信息
        HistoricProcessInstance historicProcessInstance = historyService
                .createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();

        if (historicProcessInstance == null) {
            // 处理流程实例不存在的情况
            return null;
        }

        // 2. 填充流程实例基本信息
        detail.setProcessInstanceId(historicProcessInstance.getId());
        detail.setProcessDefinitionId(historicProcessInstance.getProcessDefinitionId());
        detail.setStartTime(historicProcessInstance.getStartTime());
        detail.setEndTime(historicProcessInstance.getEndTime());
        detail.setBusinessKey(historicProcessInstance.getBusinessKey());

        // 3. 查询已审批的历史活动节点（已完成的节点）
        List<HistoricActivityInstance> historicActivities = historyService
                .createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricActivityInstanceStartTime().asc()
                .list();

        // 转换为自定义的ActivityInfo对象以便于前端展示
        List<ActivityInfo> approvedNodes = historicActivities.stream()
                .filter(activity -> activity.getEndTime() != null) // 已完成的活动
                .map(activity -> {
                    ActivityInfo nodeInfo = new ActivityInfo();
                    nodeInfo.setActivityId(activity.getActivityId());
                    nodeInfo.setActivityName(activity.getActivityName());
                    nodeInfo.setActivityType(activity.getActivityType());
                    nodeInfo.setStartTime(activity.getStartTime());
                    nodeInfo.setEndTime(activity.getEndTime());
                    nodeInfo.setAssignee(activity.getAssignee()); // 处理人信息
                    return nodeInfo;
                })
                .collect(Collectors.toList());

        detail.setApprovedNodes(approvedNodes);

        // 4. 查询当前进行中的节点
        List<String> currentActivityIds = new ArrayList<>();

        // 首先检查流程实例是否仍在运行
        ProcessInstance runtimeInstance = runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();

        if (runtimeInstance != null && !runtimeInstance.isEnded()) {
            // 流程未结束，获取当前活动节点ID
            currentActivityIds = runtimeService.getActiveActivityIds(processInstanceId);
            detail.setStatus("RUNNING");
        } else {
            // 流程已结束
            detail.setStatus("COMPLETED");
        }

        // 5. 获取当前节点的详细信息
        List<ActivityInfo> currentNodes = new ArrayList<>();
        if (!currentActivityIds.isEmpty()) {
            for (String activityId : currentActivityIds) {
                // 可以根据activityId从historicActivities中查找详细信息，或者通过BpmnModel获取
                HistoricActivityInstance currentActivity = historicActivities.stream()
                        .filter(activity -> activityId.equals(activity.getActivityId()) && activity.getEndTime() == null)
                        .findFirst()
                        .orElse(null);

                if (currentActivity != null) {
                    ActivityInfo currentNode = new ActivityInfo();
                    currentNode.setActivityId(currentActivity.getActivityId());
                    currentNode.setActivityName(currentActivity.getActivityName());
                    currentNode.setActivityType(currentActivity.getActivityType());
                    currentNode.setStartTime(currentActivity.getStartTime());
                    currentNode.setAssignee(currentActivity.getAssignee());
                    currentNodes.add(currentNode);
                }
            }
        }
        detail.setCurrentNodes(currentNodes);

        return detail;
    }


    /**
     * 处理任务
     */
    @PostMapping("/complete/{taskId}")
    public ResponseEntity<String> completeTask(@PathVariable String taskId, @RequestBody Map<String, Object> variables) {

        taskService.complete(taskId, variables);

        return ResponseEntity.ok("任务处理完成");
    }

}